package com.cjm.algorithm.leetcode;

/**
 * 几张卡牌 排成一行，每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
 * 每次行动，你可以从行的开头或者末尾拿一张卡牌，最终你必须正好拿 k 张卡牌。
 * 你的点数就是你拿到手中的所有卡牌的点数之和。
 * 给你一个整数数组 cardPoints 和整数 k，请你返回可以获得的最大点数。
 * 示例 1：
 * 输入：cardPoints = [1,2,3,4,5,6,1], k = 3
 * 输出：12
 * 解释：第一次行动，不管拿哪张牌，你的点数总是 1 。但是，先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌，最终
 * 示例 2：
 * 输入：cardPoints = [2,2,2], k = 2
 * 输出：4
 * 解释：无论你拿起哪两张卡牌，可获得的点数总是 4 。
 * 示例 3：
 * 输入：cardPoints = [9,7,7,9,7,7,9], k = 7
 * 输出：55
 * 解释：你必须拿起所有卡牌，可以获得的点数为所有卡牌的点数之和。
 * 示例 4：
 * 输入：cardPoints = [1,1000,1], k = 1
 * 输出：1
 * 解释：你无法拿到中间那张卡牌，所以可以获得的最大点数为 1 。
 * 示例 5：
 * 输入：cardPoints = [1,79,80,1,1,1,200,1], k = 3
 * 输出：202
 * 提示：
 * • 1 <= cardPoints.length <= 10
 * 5
 * • 1 <= cardPoints[i] <= 10
 * 4
 * • 1 <= k <= cardPoints.length
 */
public class Ti1423Medium {
    public static void main(String[] args) {

    }

    /**
     * 简单的推导
     * cardPoints k, 头或尾
     *
     * 从两边选择卡片， 选择k张， 卡片的总数量为n张， 即有n-k张不被选择。所有卡
     * 边的总和为sum固定，要使选择的k张的总和最大， 反过来就是要让不被选择的n-k
     * 张的总和最小。可以使用滑动窗口来计算n-k张卡片的最小总和min, 最终答案
     * sum - min。以下代码可以作为滑动窗口模板使用：
     *     你会发现以下代码643很相似， 因为是一套模板， 所以这道题是简单题，只是
     * 多了一个小学奥数难度的等式推导过程~
     * 1、初始化将滑动窗口压满， 取得第一个滑动窗口的目标值；
     * 2、继续滑动窗口， 每往前滑动一次， 需要删除一个和添加一个元素。
     *
     * @param nums
     * @param k
     * @return
     */
    public int maxScore(int[] nums, int k) {
        int length = nums.length;
        int min = 0, ans = 0, sum = 0;
        for (int i = 0; i < k; i++) {
            ans += nums[i];
            sum += nums[i];
        }
        min = ans;
        for(int i = k;i<length;i++) {
            ans += nums[i];
            ans -= nums[i - k];
            sum += nums[i];
            min = Math.min(ans, min);
        }
        return sum - min;
    }

}
